﻿using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Net;
using System.IO;
using System.Collections.Specialized;
using System.Text.RegularExpressions;
using System.Collections.Generic;
using System.Text;
using System.Globalization;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Runtime.InteropServices;

public class oAuthSina : oAuthBase
{
    public enum Method { GET, POST, PUT, DELETE };

    //private const string REQUEST_TOKEN = "http://api.weibo.com/oauth/request_token";
    //private const string AUTHORIZE = "http://api.weibo.com/oauth/authorize";
    //private const string ACCESS_TOKEN = "http://api.weibo.com/oauth/access_token";
    private const string REQUEST_TOKEN = "http://api.t.sina.com.cn/oauth/request_token";
    private const string AUTHORIZE = "http://api.t.sina.com.cn/oauth/authorize";
    private const string ACCESS_TOKEN = "http://api.t.sina.com.cn/oauth/access_token";
    private string _appKey = "";
    private string _appSecret = "";
    private string _token = "";
    private string _tokenSecret = "";

    #region Properties
    public string appKey
    {
        get
        {
            if (_appKey.Length == 0)
            {
                _appKey = "1669480258";
            }
            return _appKey;
        }
        set { _appKey = value; }
    }
    public string appSecret
    {
        get
        {
            if (_appSecret.Length == 0)
            {
                _appSecret = "eb7385045e4fb40f4ccd6d7e2da015fc";
            }
            return _appSecret;
        }
        set { _appSecret = value; }
    }
    public string token { get { return _token; } set { _token = value; } }
    public string tokenSecret { get { return _tokenSecret; } set { _tokenSecret = value; } }
    private NetworkCredential mycred = new NetworkCredential();
    private CookieContainer cc = new CookieContainer();
    private string cookiestring=null;

    #endregion
    
    [DllImport("wininet.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern bool InternetSetCookie(string lpszUrlName, string lbszCookieName, string lpszCookieData);

    [DllImport("wininet.dll", CharSet = CharSet.Auto, SetLastError = true)]
    public static extern bool InternetGetCookie(string lpszUrlName, string lbszCookieName, StringBuilder lpszCookieData, ref int lpdwSize);

    [DllImport("kernel32.dll")]
    public static extern Int32 GetLastError();

    public void LoginWithCookie(string cookie)
    {
        cookiestring = cookie;
    }

    private string login4Pin(string postdata)
    {
        string url = AUTHORIZE;
        string msg = _WebRequest(oAuthSina.Method.POST, url, postdata);
        string pin="";

        int index = -1;
        index = msg.IndexOf("获取到的授权码");
        if (index != -1)
        {
            string pattern = ">";
            index = msg.IndexOf(pattern, index) + pattern.Length;
            pin = msg.Substring(index, msg.IndexOf("</span>", index) - index);
        }
   
        return pin; 
    }
    private string parseLoginPage(string html)
    {
        string retdata="";
        string pattern;
        
        string saction, sregCallback, soauth_token, soauth_callback, sfrom;
        string suserId, spasswd;

        int index = -1,tmp=-1;
        tmp = html.IndexOf("<form name=\"authZForm\"");
        
        if (tmp != -1)
        {
            index = html.IndexOf("name=\"action\"", tmp);
            pattern = "value=\"";
            index = html.IndexOf(pattern, index) + pattern.Length;
            saction = html.Substring(index, html.IndexOf("\"", index) - index);

            index = html.IndexOf("name=\"regCallback\"", tmp);
            pattern = "value=\"";
            index = html.IndexOf(pattern, index) + pattern.Length;
            sregCallback = html.Substring(index, html.IndexOf("\"", index) - index);

            index = html.IndexOf("name=\"oauth_token\"", tmp);
            pattern = "value=\"";
            index = html.IndexOf(pattern, index) + pattern.Length;
            soauth_token = html.Substring(index, html.IndexOf("\"", index) - index);

            index = html.IndexOf("name=\"oauth_callback\"", tmp);
            pattern = "value=\"";
            index = html.IndexOf(pattern, index) + pattern.Length;
            soauth_callback = html.Substring(index, html.IndexOf("\"", index) - index);

            index = html.IndexOf("name=\"from\"", tmp);
            pattern = "value=\"";
            index = html.IndexOf(pattern, index) + pattern.Length;
            sfrom = html.Substring(index, html.IndexOf("\"", index) - index);

            suserId = mycred.UserName;
            spasswd = mycred.Password;

            retdata = "action=" + saction + "&regCallback=" + sregCallback + "&oauth_token=" + soauth_token + "&oauth_callback="
                + soauth_callback + "&from=" + sfrom + "&userId=" + suserId + "&passwd=" + spasswd;
        }
        
        return retdata;
    }
    public void Login(string username, string password)
    {
        mycred.UserName = username;
        mycred.Password = password;
        cookiestring = "";

        RequestTokenGet();
        string url=AuthorizationGet();
        string retmsg=oAuthWebRequest(oAuthSina.Method.GET, url, "");
        string loginData = parseLoginPage(retmsg);
        this.Verifier = login4Pin(loginData);
        AccessTokenGet();

    }
    //private string _WebRequest(Method method, string url, string postData)
    //{
    //    HttpWebRequest webRequest = null;
    //    StreamWriter requestWriter = null;
    //    string responseData = "";
    //    //string usernamePassword="";
    //    //CredentialCache mycache=null;

    //    //if (isBasicAuthentication)
    //    //{
    //    //    //注意这里的格式哦，为 "username:password"
    //    //    usernamePassword = mycred.UserName + ":" + mycred.Password;
    //    //    mycache = new CredentialCache();
    //    //    mycache.Add(new Uri(url), "Basic", mycred);
    //    //}
    //    webRequest = System.Net.WebRequest.Create(url) as HttpWebRequest;
    //    if (cc != null)
    //    {
    //        webRequest.CookieContainer=cc;
    //        string[] cookies = cookiestring.Split(";".ToCharArray());

    //        foreach (string mycookie in cookies)
    //        {
    //            cc.SetCookies(webRequest.RequestUri, mycookie);
    //        }
    //    }
        
    //    //if (isBasicAuthentication)
    //    //{
    //    //    webRequest.Credentials = mycache;
    //    //    webRequest.Headers.Add("Authorization", "Basic " + Convert.ToBase64String(new ASCIIEncoding().GetBytes(usernamePassword)));
    //    //}
    //    webRequest.Headers.Add("Pragma: no-cache");
    //    webRequest.Method = method.ToString();
    //    webRequest.ServicePoint.Expect100Continue = false;
     
    //    if (method == Method.POST)
    //    {
    //        webRequest.ContentType = "application/x-www-form-urlencoded";
    //        requestWriter = new StreamWriter(webRequest.GetRequestStream());
    //        try
    //        {
    //            requestWriter.Write(postData);
    //        }
    //        catch
    //        {
    //            throw;
    //        }
    //        finally
    //        {
    //            requestWriter.Close();
    //            requestWriter = null;
    //        }
    //    }

    //    responseData = _WebResponseGet(webRequest);

    //    webRequest = null;

    //    return responseData;

    //}
    public string oAuthWebRequest(Method method, string url, string postData)
    {
        string outUrl = "";
        string querystring = "";
        string ret = "";
        postData += "&source=" + appKey;
        if (method == Method.POST)
        {
            if (postData.Length > 0)
            {
                NameValueCollection qs = HttpUtility.ParseQueryString(postData);
                postData = "";
                foreach (string key in qs.AllKeys)
                {
                    if (postData.Length > 0)
                    {
                        postData += "&";
                    }
                    qs[key] = HttpUtility.UrlEncode(qs[key]);
                    qs[key] = this.UrlEncode(qs[key]);
                    postData += (key + "=" + qs[key]);

                }
                if (url.IndexOf("?") > 0)
                {
                    url += "&";
                }
                else
                {
                    url += "?";
                }
                url += postData;
            }
        }

        Uri uri = new Uri(url);

        string nonce = this.GenerateNonce();
        string timeStamp = this.GenerateTimeStamp();

        //Generate Signature
        string sig = this.GenerateSignature(uri,
            this.appKey,
            this.appSecret,
            this.token,
            this.tokenSecret,
            method.ToString(),
            timeStamp,
            nonce,
            out outUrl,
            out querystring);


        querystring += "&oauth_signature=" + HttpUtility.UrlEncode(sig);

        if (method == Method.POST)
        {
            postData = querystring;
            querystring = "";
        }

        if (querystring.Length > 0)
        {
            outUrl += "?";
        }

        if (method == Method.POST || method == Method.GET)
            ret = _WebRequest(method, outUrl + querystring, postData);

        return ret;
    }

    private string _WebRequest(Method method, string url, string postData)
    {
        HttpWebRequest webRequest = null;
        StreamWriter requestWriter = null;
        string responseData = "";

        webRequest = System.Net.WebRequest.Create(url) as HttpWebRequest;
        webRequest.Method = method.ToString();
        webRequest.ServicePoint.Expect100Continue = false;

        if (method == Method.POST)
        {
            webRequest.ContentType = "application/x-www-form-urlencoded";
            requestWriter = new StreamWriter(webRequest.GetRequestStream());
            try
            {
                requestWriter.Write(postData);
            }
            catch
            {
                throw;
            }
            finally
            {
                requestWriter.Close();
                requestWriter = null;
            }
        }

        responseData = _WebResponseGet(webRequest);

        webRequest = null;

        return responseData;

    }

    private string _WebResponseGet(HttpWebRequest webRequest)
    {
        StreamReader responseReader = null;
        HttpWebResponse response = null;

        string responseData = "";
        try
        {
            response=(HttpWebResponse)webRequest.GetResponse();
            response.Cookies = cc.GetCookies(webRequest.RequestUri);
            responseReader = new StreamReader(response.GetResponseStream());
            responseData = responseReader.ReadToEnd();
            
        }
        catch
        {
            throw;
        }
        finally
        {
            webRequest.GetResponse().GetResponseStream().Close();
            responseReader.Close();
            responseReader = null;
        }

        return responseData;
    }
    //public string oAuthWebRequest(Method method, string url, string postData)
    //{
    //    string outUrl = "";
    //    string querystring = "";
    //    string ret = "";
    //    postData += "&source=" + appKey;
    //    if (method == Method.POST)
    //    {
    //        if (postData.Length > 0)
    //        {
    //            NameValueCollection qs = HttpUtility.ParseQueryString(postData);
    //            postData = "";
    //            foreach (string key in qs.AllKeys)
    //            {
    //                if (postData.Length > 0)
    //                {
    //                    postData += "&";
    //                }
    //                qs[key] = HttpUtility.UrlEncode(qs[key]);
    //                qs[key] = this.UrlEncode(qs[key]);
    //                postData += (key + "=" + qs[key]);

    //            }
    //            if (url.IndexOf("?") > 0)
    //            {
    //                url += "&";
    //            }
    //            else
    //            {
    //                url += "?";
    //            }
    //            url += postData;
    //        }
    //    }

    //    Uri uri = new Uri(url);

    //    string nonce = this.GenerateNonce();
    //    string timeStamp = this.GenerateTimeStamp();

    //    //Generate Signature
    //    string sig = this.GenerateSignature(uri,
    //        this.appKey,
    //        this.appSecret,
    //        this.token,
    //        this.tokenSecret,
    //        method.ToString(),
    //        timeStamp,
    //        nonce,
    //        out outUrl,
    //        out querystring);


    //    querystring += "&oauth_signature=" + HttpUtility.UrlEncode(sig);

    //    if (method == Method.POST)
    //    {
    //        postData = querystring;
    //        querystring = "";
    //    }

    //    if (querystring.Length > 0)
    //    {
    //        outUrl += "?";
    //    }

    //    if (method == Method.POST)
    //        ret = _WebRequest(method, outUrl + querystring, postData);
    //    else if (method == Method.GET)//GET
    //    {
    //        ret = _WebRequest(method, outUrl + querystring + "&"+postData, "");
    //    }

    //    return ret;
    //}

    public void RequestTokenGet()
    {
        string response = oAuthWebRequest(Method.GET, REQUEST_TOKEN, String.Empty);
        if (response.Length > 0)
        {
            NameValueCollection qs = HttpUtility.ParseQueryString(response);
            if (qs["oauth_token"] != null)
            {
                this.token = qs["oauth_token"];
                this.tokenSecret = qs["oauth_token_secret"];
            }
        }
    }

    public string AuthorizationGet()
    {
        string ret = null;
        ret = AUTHORIZE + "?oauth_token=" + this.token;
        return ret;
    }

    public void AccessTokenGet()
    {
        string response = oAuthWebRequest(Method.GET, ACCESS_TOKEN, string.Empty);

        if (response.Length > 0)
        {
            NameValueCollection qs = HttpUtility.ParseQueryString(response);
            if (qs["oauth_token"] != null)
            {
                this.token = qs["oauth_token"];
            }
            if (qs["oauth_token_secret"] != null)
            {
                this.tokenSecret = qs["oauth_token_secret"];
            }
        }
    }

    public string oAuthWebRequestWithPic(Method method, string url, string postData, string filepath)
    {
        var UploadApiUrl = url;
        string status = postData.Split('=').GetValue(1).ToString();
        postData += "&source=" + appKey;

        if (postData.Length > 0)
        {
            NameValueCollection qs = HttpUtility.ParseQueryString(postData);
            postData = "";
            foreach (string key in qs.AllKeys)
            {
                if (postData.Length > 0)
                {
                    postData += "&";
                }
                qs[key] = HttpUtility.UrlEncode(qs[key]);
                qs[key] = this.UrlEncode(qs[key]);
                postData += (key + "=" + qs[key]);

            }
            if (url.IndexOf("?") > 0)
            {
                url += "&";
            }
            else
            {
                url += "?";
            }
            url += postData;
        }

        var oauthSignaturePattern = "OAuth oauth_consumer_key=\"{0}\", oauth_signature_method=\"HMAC-SHA1\",oauth_timestamp=\"{1}\", oauth_nonce=\"{2}\", oauth_version=\"1.0\", oauth_token=\"{3}\",oauth_signature=\"{4}\"";

        var contentEncoding = "iso-8859-1";

        string normalizedString, normalizedParameters;
        var timestamp = this.GenerateTimeStamp();
        var nounce = this.GenerateNonce();

        var signature = this.GenerateSignature(
                            new Uri(url),
                            this.appKey,
                            this.appSecret,
                            this.token,
                            this.tokenSecret,
                            method.ToString(),
                            timestamp,
                            nounce,
                            out normalizedString,
                            out normalizedParameters);
        signature = HttpUtility.UrlEncode(signature);

        var boundary = Guid.NewGuid().ToString();
        var request = (HttpWebRequest)System.Net.WebRequest.Create(UploadApiUrl);

        request.PreAuthenticate = true;
        request.AllowWriteStreamBuffering = true;
        request.Method = method.ToString();
        request.UserAgent = "Jakarta Commons-HttpClient/3.1";
        var authorizationHeader = string.Format(
                                    CultureInfo.InvariantCulture,
                                    oauthSignaturePattern,
                                    this.appKey,
                                    timestamp,
                                    nounce,
                                    this.token,
                                    signature);
        request.Headers.Add("Authorization", authorizationHeader);

        var header = string.Format("--{0}", boundary);
        var footer = string.Format("--{0}--", boundary);

        var contents = new StringBuilder();
        request.ContentType = string.Format("multipart/form-data; boundary={0}", boundary);
        contents.AppendLine(header);
        contents.AppendLine(String.Format("Content-Disposition: form-data; name=\"{0}\"", "status"));
        contents.AppendLine("Content-Type: text/plain; charset=US-ASCII");
        contents.AppendLine("Content-Transfer-Encoding: 8bit");
        contents.AppendLine();
        contents.AppendLine(status);

        contents.AppendLine(header);
        contents.AppendLine(string.Format("Content-Disposition: form-data; name=\"{0}\"", "source"));
        contents.AppendLine("Content-Type: text/plain; charset=US-ASCII");
        contents.AppendLine("Content-Transfer-Encoding: 8bit");
        contents.AppendLine();
        contents.AppendLine(this.appKey);


        contents.AppendLine(header);
        string fileHeader = string.Format("Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"", "pic", filepath);
        string fileData = System.Text.Encoding.GetEncoding(contentEncoding).GetString(File.ReadAllBytes(@filepath));

        contents.AppendLine(fileHeader);
        contents.AppendLine("Content-Type: application/octet-stream; charset=UTF-8");
        contents.AppendLine("Content-Transfer-Encoding: binary");
        contents.AppendLine();
        contents.AppendLine(fileData);
        contents.AppendLine(footer);

        byte[] bytes = Encoding.GetEncoding(contentEncoding).GetBytes(contents.ToString());
        request.ContentLength = bytes.Length;

        var requestStream = request.GetRequestStream();
        try
        {
            requestStream.Write(bytes, 0, bytes.Length);
        }
        catch
        {
            throw;
        }
        finally
        {
            requestStream.Close();
            requestStream = null;
        }
        return _WebResponseGet(request);
    }
}